﻿/******************************************************************************
 * Name         : EventLoop.hpp
 * Author       : 671643387
 * Date         : 2015年9月6日
 * Description  : 事件循环，占用线程资源，负责网络IO的派发和处理发送到其的消息
 *****************************************************************************/

#ifndef NET_EVENTLOOP_HPP_
#define NET_EVENTLOOP_HPP_

#include <boost/noncopyable.hpp>
#include <boost/function.hpp>
#include <dev/base/Mutex.hpp>
#include <dev/base/LockGuard.hpp>
#include <dev/base/LockedQueue.hpp>
#include <dev/base/TimeUtil.hpp>
#include <dev/net/Reactor.hpp>

namespace dev
{
    namespace net
    {
        class TcpWorker;
        class TcpServer;

        /**
         * @brief 事件循环
         */
        class EventLoop : public boost::noncopyable
        {
        private:
            friend class TcpWorker;
            friend class TcpServer;
        public:
            typedef boost::function<void(Socket*)> PassSocketPointerCB;

        public:
            enum Status
            {
                READY,      // 准备就绪
                RUNNING,    // 执行中
                EXITING,    // 退出中
                EXIT        // 已退出
            };
        public:
            EventLoop();
            EventLoop(Reactor* rector);
            ~EventLoop();

        public:

            /**
             * @brief 执行事件循环
             */
            int run(void);

            /**
             * @brief 停止事件循环
             */
            void stop(void);

            /**
             * @brief 在事件循环执行这个函数
             * @param handler   需要执行的函数
             */
            void queueEvent(boost::function<void(void)> handler);

        public:
            /**
             * @brief 绑定套接字到事件循环，事件循环会负责检查这个套接字上的事件并派发
             * @param sock      套接字指针
             * @param events    注册到这个套接字的事件
             * @param handelr   事件处理器
             */
            void addSocket(Socket* sock, Reactor::EventType events, SocketEventHandler* handler);

            /**
             * @brief 从事件循环移除这个套接字
             * @param sock      套接字指针
             */
            void removeSocket(Socket* sock);

        public:
            /**
             * @brief 获取事件循环状态
             * @return Status
             */
            Status getStatus(void) const { return status_; }

            /**
             * @brief 获取事件循环的网络反应器
             * @return ReactorPtr
             */
            ReactorPtr& getReactor(void) { return reactor_; }

            /**
             * @brief 获取事件循环的帧时间
             * @return base::mtime_t
             */
            base::mtime_t getFrameTime(void) const { return frameTime_; }

            /**
             * @brief 设置事件循环的帧时间
             * @param time  帧时间
             */
            void setFrameTime(base::mtime_t time) { frameTime_ = time; }

            /**
             * @brief 获取事件循环的ID
             * @return int
             */
            int getId(void) const { return id_; }

            /**
             * @brief 获取事件循环已经循环的次数
             * @return unsigned long long
             */
            unsigned long long getLoopCounter(void) const { return loopCounter_; }

            /**
             * @brief 获取事件循环当前执行一帧消耗的时间
             * @return base::mtime_t
             */
            base::mtime_t getFrameSystemTime(void) const { return frameSysTime_; }

            /**
             * @brief 设置事件循环套接字移除回调函数，当完成移除这个套接字时会调用
             * @param callback  回调函数
             */
            void setRemoveSocketCallback(PassSocketPointerCB callback) { removeSocketCB_ = callback; }

        private:

            /**
             * @brief 设置事件循状态
             * @param status
             */
            void setStatus(Status status) { status_ = status; }

        private:
            void doAddSocket(Socket* sock, Reactor::EventType events, SocketEventHandler* handler);
            void doRemoveSocket(Socket* sock);

        private:
            int id_;                                                    // 标志ID
            Status status_;                                             // 状态
            base::mtime_t frameTime_;                                   // 帧时间(毫秒)，默认每秒50帧
            base::mtime_t frameSysTime_;                                // 每帧系统执行的时间
            ReactorPtr reactor_;                                        // 网络消息派发器

            volatile unsigned long long loopCounter_;                   // 循环次数

        private:
            PassSocketPointerCB removeSocketCB_;                        // 套接字移除回调

        private:
            struct _Event
            {
                base::mtime_t time;                                    // 事件插入时间
                boost::function<void(void)> handler;                   // 事件处理器
            };
            base::LockedQueue<struct _Event, base::Mutex>  events_;     // 事件队列

        private:
            /* 负责从事件队列提取事件时过滤事件 */
            class Checker
            {
            public:
                Checker() : time_(base::TimeUtil::fromStartup()){}
                bool process(struct _Event& event)
                {
                    return (event.time <= time_);
                }
            private:
                base::mtime_t time_;
            };
        };
    }
}

#endif /* NET_EVENTLOOP_HPP_ */
